<html>
    <head>
        <title>验证</title>
    </head>
    <body>
        <script>
            /*
                 3、Validation 验证

                                        实体扩展系统允许你以多种方式定义扩展属性的验证。

                                        ①、数据注释特性

                                                            Attributes是与此属性关联的特性列表。

                                                            下面的示例代码将两个数据注释验证特性添加到属性中：

                                                                property =>
                                                                {
                                                                    property.Attributes.Add(new RequiredAttribute());
                                                                    property.Attributes.Add(new StringLengthAttribute(64) {MinimumLength = 4});
                                                                }

                                                        当你运行应用程序时，你会看到验证开箱即用：  表单上会有相关验证。

                                                        由于我们已经添加了RequiredAttribute，它不允许将其留空。验证系统工作：

                                                                在用户交互界面上（带有自动本地化）。

                                                                在HTTP API上。即使你直接执行HTTP请求，你也会收到带有正确HTTP状态代码的验证错误

                                                                在实体的SetProperty(...)方法上（如果你想知道SetProperty()方法是什么，请参阅文档）。https://abp.io/docs/latest/framework/architecture/domain-driven-design/entities

                                                        因此，它会自动进行全栈验证。
                                        
                                        ②、默认验证特性：

                                                  当你创建某些类型的属性时，会自动添加一些特性：

                                                        RequiredAttribute。如果要允许空值，请使属性为空（例如int?）。

                                                        EnumDataTypeAttribute，以防止设置无效的枚举值。

                                                  使用property.Attributes.Clear();如果你不想要这些特性。

                                         
                                        ③、验证操作

                                                  验证操作允许你执行自定义代码来执行验证。

                                                  下面的示例检查SocialSecurityNumber是否以B开头，如果是，则添加验证错误：

                                                        property =>
                                                        {
                                                            property.Attributes.Add(new RequiredAttribute());
                                                            property.Attributes.Add(new StringLengthAttribute(64) {MinimumLength = 4});

                                                            property.Validators.Add(context =>
                                                            {
                                                                if (((string) context.Value).StartsWith("B"))
                                                                {
                                                                    context.ValidationErrors.Add(
                                                                        new ValidationResult(
                                                                            "Social security number can not start with the letter 'B', sorry!",
                                                                            new[] {"extraProperties.SocialSecurityNumber"}
                                                                        )
                                                                    );
                                                                }
                                                            });

                                                        }
                                                  在这种情况下使用RegularExpressionAttribute可能更好，但这只是一个例子。

                                                  无论如何，如果你输入一个以字母B开头的值，你在保存表单时会收到以下错误：

                                                  ★、上下文对象：

                                                        context对象具有可用于自定义验证操作的有用属性。

                                                        例如，你可以使用context.ServiceProvider来解析来自依赖注入系统的服务。

                                                        下面的示例获取本地化程序并添加本地化错误消息：

                                                                if (((string) context.Value).StartsWith("B"))
                                                                {
                                                                    var localizer = context.ServiceProvider
                                                                        .GetRequiredService<IStringLocalizer<MyProjectNameResource>>();

                                                                    context.ValidationErrors.Add(
                                                                        new ValidationResult(
                                                                            localizer["SocialSecurityNumberCanNotStartWithB"],
                                                                            new[] {"extraProperties.SocialSecurityNumber"}
                                                                        )
                                                                    );
                                                                }

                                                    注意： context.ServiceProvider可以为空！只有当你在对象上使用SetProperty(...)方法时，它才能为null。

                                                           它才能为null。因为DI系统此时不可用。

                                                           虽然这是一种罕见的情况，但当context.ServiceProvider为null时，你应该执行兜底逻辑。

                                                           对于此示例，你将添加非本地化错误消息。

                                                           这不是问题，因为将无效值设置为属性通常是程序员的错误，在这种情况下你大多不需要本地化。

                                                           论如何，即使在常规属性设置器中，你也无法使用本地化。

                                                           但是，如果你对本地化很认真，你可以抛出业务异常（请参阅异常处理文档以了解如何本地化业务异常）。
            */
        </script>
    </body>
</html>